using System;
using System.Net;
using System.Threading;

using Jeffrey.XFramework.XCrawl;
using Jeffrey.XFramework.XInteract;


namespace Jeffrey.XFramework.XNet
{
    /*
     * Implement the Http-Request via socket connection
     */
    public class XWebRequest
    {
        protected XWebRequest(CrawlUri curi)
        {
            //the HTTP header
            m_Headers = new WebHeaderCollection();
            //current processing uri
            m_Uri  = curi;
            //add the host name to headers
            m_Headers["Host"] = curi.Host;
            //the default method is set to "GET"
            m_Method = "GET";
        }

        //Create a new XRequest from specified uri...
        public static XWebRequest Create(CrawlUri curi, CrawlController cc)
        {
            XWebRequest request = new XWebRequest(curi);
            request.m_Controller = cc;

            return request;
        }
        //Create a new XRequest from specified uri and last alived request...
        public static XWebRequest Create(CrawlUri curi, XWebRequest /*LastTimeAlivedRequest*/ xRequest, CrawlController cc)
        {
            /*
             * check if the last request is still alive
             */
            if ( xRequest != null &&
                 xRequest.m_Response != null &&
                 xRequest.m_Response.m_KeepAlive
               )
            {
                /*
                 * check if current uri has the same host name with the last one
                 * and if the socket is still connected...
                 */
                if (curi.Host == xRequest.m_Uri.Host &&
                    xRequest.m_Response.m_Socket.Connected
                   )
                {
                    //reset the uri to the current uri...
                    xRequest.m_Uri = curi;
                    //reset some status of response
                    xRequest.m_Response.Reset(); 
                    //return the last request for reusing...
                    return xRequest;
                }
                else
                {
                    /*
                     * the host name is different or the socket has been disconnected...
                     * so at this time we closed the socket to release resouces...
                     */
                    xRequest.m_Response.m_Socket.Close();
                }
            }
            //return a new request
            return Create(curi, cc);
        }

        /*
         * Get XWebRsponse instance via the XWRequset
         */
        public XWebResponse GetResponse()
        {
            m_Controller.Xbuject.OnSpiderStatusChanged(new SpiderStatusPackage(Int32.Parse(Thread.CurrentThread.Name), 
                                                                               CrawlSpider.SpiderStatus.Connecting
                                                                               )
                                                      );

            /*
             * check if already has one response instance
             * and the socket has connected...
             */
            if ( m_Response == null ||
                 m_Response.m_Socket == null ||
                !m_Response.m_Socket.Connected)
            {
                /*
                 * if not, create a new response
                 * and connect, set timeout...
                 */
                m_Response = new XWebResponse(m_Controller);

                m_Response.Connect(this);
                m_Response.SetTimeOut(m_Controller.m_CrawlOrder.m_TimeOut);
            }

            if (m_Response.m_Socket.Connected)
            {
                //sent the request header to web server...
                m_Response.Sent(this);

                m_Controller.Xbuject.OnSpiderStatusChanged(new SpiderStatusPackage(Int32.Parse(Thread.CurrentThread.Name), 
                                                                                   CrawlSpider.SpiderStatus.ReceivingHeader
                                                                                   )
                                                          );
                //get the server response header...
                m_Response.ReceiveHTTPHeader();
            }

            return m_Response;
        }

        //set the socket timeout for sending and receiving
        //public Int32 TimeOut
        //{
        //    get { return m_TimeOut; }
        //    set { m_TimeOut = value; }
        //}
        //set the http method
        public String Method
        {
            get { return m_Method; }
            set { m_Method = value; }
        }

        public WebHeaderCollection HttpHeaders
        {
            get { return m_Headers; }
        }

        internal WebHeaderCollection m_Headers;

        internal CrawlUri m_Uri;
        internal String   m_Method;
        internal String   m_Header;

        internal CrawlController m_Controller;
        //internal response instance of request...
        internal XWebResponse m_Response;
    }
}
